
import {observe} from './observer/index';
import {proxy, isObject} from './util/index';
import Watcher from './observer/watcher';
import Dep from './observer/dep';

export function initState(vm){
  const opts = vm.$options;

  console.log(opts,'ooopp');
  if(opts.props){
    initProps(vm)
  }
  if(opts.methods){
    initMethods(vm)
  }
  if(opts.data){
    initData(vm)
  }
  if(opts.computed){
    initComputed(vm,opts.computed)
  }
  if(opts.watch){
    initWatch(vm,opts.watch)
  }
}
function initProps(vm){}
function initMethods(vm){}

function initData(vm){
  // console.log('数据初始化', vm.$options.data)
  let data = vm.$options.data;
  data = vm._data = typeof data === 'function' ? data.call(vm) : data;
  //代理取值
  for(let key in data){
    proxy(vm,'_data',key);
  }
  //对象劫持 用户改变数据--页面刷新 MVVM模式
  observe(data); //响应式数据
  // console.log(data,'data')
}
//内部原理是通过watcher实现的
function initComputed(vm,computed){
    //computedWatchers存放计算属性对应的watcher
    let watchers = vm._computedWatchers = {};
    for(let key in computed){
       const userDef = computed[key];
       const getter = typeof userDef === 'function' ? userDef : userDef.get();
       //获得getter函数 lazy true表示计算属性 内部根据lazy属性不去调用getter
       watchers[key] = new Watcher(vm,getter,()=>{},{lazy:true});

       //将computed定义到vm上
       defineComputed(vm,key,userDef);
    }
}
const sharedPropertyDefinition = {
  enumerable: true,
  configurable: true,
  get:()=>{},
  set:()=>{}
}
function defineComputed(target,key,userDef){
  //需要添加数据缓存效果
  if(typeof userDef === 'function'){
    sharedPropertyDefinition.get = createComputedGetter(key);
  }else{
    sharedPropertyDefinition.get = createComputedGetter(key);
    sharedPropertyDefinition.set = userDef.set || (()=>{});
  }
  Object.defineProperty(target,key,sharedPropertyDefinition);
}
function createComputedGetter (key) {
  return function(){
    //拿到了刚才的watcher
    let watcher = this._computedWatchers[key];
    if(watcher.dirty){
      //dirty为true调用用户的方法
      watcher.evaluate();
    }
    if(Dep.target){
        //watcher指计算属性watcher
        watcher.depend();
    }
    return watcher.value;
  }
}

//watch的原理是通过watcher来实现的
function initWatch(vm,watch){
  console.log(vm,watch,'watch')
  for(let key in watch){
    const handler = watch[key];
    if((Array.isArray(handler))){
       for(let i = 0;i<handler.length;i++){
         createWatcher(vm,key,handler[i]);
       }
    }else{
       createWatcher(vm,key,handler);
    }
  }
}


function createWatcher(vm,key,handler,options){
  if(isObject(handler)){
    options = handler;
    handler = handler.handler;
  }
  if(typeof handler === 'string'){//获取methods中的方法替换掉handler
      handler = vm.$options.methods[handler];
  }
  console.log(vm,'vvvvvmmm')
  return vm.$watch(key,handler,options)
}

export function stateMixin(Vue){
  Vue.prototype.$watch = function(exprOrFn,cb,options){
      console.log(exprOrFn,cb,options,'6666777')
      const vm = this;
      options.user = true; //标明是用户watcher 用于区分渲染watcher
      const watcher = new Watcher(vm,exprOrFn,cb,options);
      if(options.immediate){
          cb.call(vm,watcher.value);
      }
      return function unwatchFn(){
          watcher.teardown();
      }
  }
}
